L2norm
对输入向量进行 L2 归一化,并可选择性地应用 ReLU 或 ReLU6 激活函数。该算子首先用输入向量的 L2 范数(即欧几里得长度)去除向量中的每个元素,然后应用激活函数。
\[ \begin{align}\begin{aligned}S = \sqrt{\sum_{i=0}^{N-1} Input_i^2}\\\text{temp}_i = \frac{Input_i}{S}\\\begin{split}output_i = \begin{cases}
\min(6, \max(0, \text{temp}_i)), & \text{if } \text{is\_relu6} = 1 \\
\max(0, \text{temp}_i), & \text{if } \text{is\_relu} = 1 \\
\text{temp}_i, & \text{otherwise}
\end{cases}\end{split}\end{aligned}\end{align} \]
- 输入:
Input - 输入数据地址。
- params - 参数打包成数组。
input_shape - 输入向量的shape。
temp_sum - 多核时每个核心计算的部分累加和。
shape_num - 输入维度数量。
element_num - 输入元素数量。
norm_flag - 0 表示全局归一化,1 表示按最后一个维度归一化, mindspore源码里面没有norm_flag,需要在接口部分自己计算
is_relu - 是否进行 ReLU 操作的标志(0或1)。
is_relu6 - 是否进行 ReLU6 操作的标志(0或1)。
&epsilon - 归一化因子,防止除0,这里传指针
core_mask - 核掩码(仅共享存储版本需要)。
- 输出:
Output - 计算结果地址。
- 支持平台:
FT78NEMT7004
备注
FT78NE 支持fp32
MT7004 支持fp16, fp32
共享存储版本:
-
void hp_l2norm_s(half *Input, half *output, long long *params, int core_mask)
-
void fp_l2norm_s(float *Input, float *output, long long *params, int core_mask)
C调用示例:
1//FT78NE示例
2#include <stdio.h>
3#include <math.h>
4#include <l2norm.h> // 假设头文件名为 l2norm.h
5
6int main(int argc, char* argv[]) {
7 float* input = (float*)0x81000000;
8 float* output = (float*)0x82000000;
9
10 int input_shape[4] = {16, 8, 16, 8};
11 int is_relu = 1;
12 int is_relu6 = 1;
13 int norm_flag = 1; //0:全部norm,1:按最后一个维度norm
14 int shape_num = 4;
15 int element_num = input_shape[0] * input_shape[1] * input_shape[2] * input_shape[3];
16 float* temp_sum = (float*)0x10040000;
17 float epsilon = 1e-6;
18
19 srand(seed++);
20
21 int i;
22 for (i = 0; i < element_num; i++) {
23 input[i] = (float)(rand() % 20 + 1);
24 }
25
26 long long params[10];
27
28 params[0] = (long long)input_shape;
29 params[1] = (long long)temp_sum;
30 params[2] = (long long)shape_num;
31 params[3] = (long long)element_num;
32 params[4] = (long long)norm_flag;
33 params[5] = (long long)is_relu;
34 params[6] = (long long)is_relu6;
35 params[7] = (long long)ε //这里传指针
36
37 int core_mask = 0b1111;
38 fp_l2norm_s(input, output, (long long *)params, core_mask);
39 return 0;
40}
私有存储版本:
-
void hp_l2norm_p(half *Input, half *output, long long *params, int is_relu6)
-
void fp_l2norm_p(float *Input, float *output, long long *params)
C调用示例:
1//FT78NE示例
2#include <stdio.h>
3#include <math.h>
4#include <l2norm.h> // 假设头文件名为 l2norm.h
5
6int main(int argc, char* argv[]) {
7 float* input = (float*)0x10010000;
8 float* output = (float*)0x10020000;
9
10 int input_shape[4] = {16, 8, 16, 8};
11 int is_relu = 1;
12 int is_relu6 = 1;
13 int norm_flag = 1; //0:全部norm,1:按最后一个维度norm
14 int shape_num = 4;
15 int element_num = input_shape[0] * input_shape[1] * input_shape[2] * input_shape[3];
16 float* temp_sum = (float*)0x10040000;
17 float epsilon = 1e-6;
18
19 srand(seed++);
20
21 int i;
22 for (i = 0; i < element_num; i++) {
23 input[i] = (float)(rand() % 20 + 1);
24 }
25
26 long long params[10];
27
28 params[0] = (long long)input_shape;
29 params[1] = (long long)temp_sum;
30 params[2] = (long long)shape_num;
31 params[3] = (long long)element_num;
32 params[4] = (long long)norm_flag;
33 params[5] = (long long)is_relu;
34 params[6] = (long long)is_relu6;
35 params[7] = (long long)ε //这里传指针
36
37 fp_l2norm_p(input, output, (long long *)params);
38 return 0;
39}